package net.gdface.facelog;

import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.Arrays;
import java.util.List;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableMap.Builder;

import gu.simplemq.IMessageQueueFactory;
import gu.simplemq.MessageQueueFactorys;
import gu.simplemq.MessageQueueType;
import net.gdface.utils.Platform;

import static com.google.common.base.Preconditions.*;

/**
 * 本地(独立,命令行启动) ACTIVEMQ 服务控制器<br>
 * @author guyadong
 *
 */
class ActivemqControllerLocal extends ActivemqController {
	/** 环境变量ACTIVEMQ_SUNJMX_START的值 */
	private static final String ENV_JMX_START = String.format("ACTIVEMQ_SUNJMX_START="
			+ "-Dcom.sun.management.jmxremote "
			+ "-Dcom.sun.management.jmxremote.authenticate=false "
			+ "-Dcom.sun.management.jmxremote.port=%d "
			+ "-Dcom.sun.management.jmxremote.ssl=false",JMXPORT);
	private volatile String exe;
	protected ActivemqControllerLocal(IMessageQueueFactory factory) {
		super(factory);
	}
	/**
	 * @return 返回 ACTIVEMQ 的启动脚本，如果配置文件中未定义则抛出异常
	 */
	private String getExe(){
		// double check
		if(exe == null){
			synchronized (this) {
				if(exe == null){
					exe = checkNotNull(CONFIG.getString(ACTIVEMQ_EXE),
							"NOT DEFINE PROPERTY(参数没有定义) %s",ACTIVEMQ_EXE);
				}
			}
		}
		return exe;
	}
	
	private List<String> wrapCmd(String cmd){
		if(Platform.isWindows()){
			return Arrays.asList("cmd","/c","\"" + cmd + "\"");
		}else if(Platform.isLinux()){
			return Arrays.asList("bash","-c","\"" + cmd + "\"");
		} else {
			throw new UnsupportedOperationException("UNSUPPORTED OS(不支持的操作系统) " + System.getProperty("os.name"));
		}
	}
	private List<String> wrapJmxstart(List<String> cmd,String action){
		if("start".equals(action)){
			if(Platform.isWindows()){
				/** 对启动服务命令添加  ACTIVEMQ_SUNJMX_START 环境变量启动JMX */
				cmd.add(0, "set " + ENV_JMX_START );
			}else if(Platform.isLinux()){
				/** 对启动服务命令添加  ACTIVEMQ_SUNJMX_START 环境变量启动JMX */
				cmd.add(0, ENV_JMX_START );
			}else {
				throw new UnsupportedOperationException("UNSUPPORTED OS(不支持的操作系统) " + System.getProperty("os.name"));
			}
		}
		return cmd;
	}
	private List<String> wrapJavahome(List<String> cmd,String javahome){
		if(Platform.isWindows()){
			cmd.add(0, String.format("set PATH=%s/bin;%%PATH%%",javahome));
			cmd.add(0, String.format("set JAVA_HOME=%s",javahome));
		}else if(Platform.isLinux()){
			cmd.add(0, String.format("PATH=%s/bin:%%PATH%%",javahome));
			cmd.add(0, String.format("JAVA_HOME=%s",javahome));
		}else {
			throw new UnsupportedOperationException("UNSUPPORTED OS(不支持的操作系统) " + System.getProperty("os.name"));
		}
		return cmd;
	}
	/**
	 * 生成启动/停止 ACTIVEMQ 服务的命令
	 * @param action 'start' or 'stop'
	 * @return 命令参数列表
	 */
	private List<String> makeCommand(String action){
		List<String> cmd = wrapJmxstart(Lists.newArrayList(String.format("%s %s",getExe(),action)),action);
		/** 
		 * ACTIVEMQ 在 JAVA7 下停止不方便，所以要求在 JAVA8 上运行
		 * 当前服务运行在 JAVA7 环境时，要求必须在配置文件用 'activemq.java8home' 参数指定JAVA8的位置，否则抛出异常
		 */
		if(CONFIG.containsKey(JAVA_JAVA8HOME)){
			String javahome = CONFIG.getString(JAVA_JAVA8HOME, "");
			 
			if(!javahome.isEmpty()){
				wrapJavahome(cmd,javahome);							
			}else {
				checkState(JdkVersion.getVersion() >= 8,
						"JAVA 8 REQUIRED for running ActiveMQ,but not defined property  %s FOR java 8 home"
						+ "(启动ActiveMQ要求JAVA 8,但未定义 %s 参数)",
						JAVA_JAVA8HOME,JAVA_JAVA8HOME);
			}
		}
		return wrapCmd(Joiner.on(" && ").join(cmd));
	}

	@Override
	protected List<String> makeStartCommand(){
		return makeCommand("start");
	}
	@Override
	protected void shutdownLocalServer() {
		String name = serviceName();
		ServiceConstant.logger.info("shutdown {} server(关闭{}服务)",name,name);
		List<String> args = makeCommand("stop");
		String cmd = Joiner.on(' ').join(args);
		ServiceConstant.logger.info("cmd(关闭命令): {}",cmd);
		try {
			new ProcessBuilder(args)
					.redirectError(Redirect.INHERIT)
					.redirectOutput(Redirect.INHERIT)
					.start();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	boolean init() {
		super.init();
		if(this.factory != null){
			return false;
		}
		// factory 未初始化时需要对之初始化
		// 更新为准确的值
		location = getLocalTransportURI(PROTOCOL_AMQP);
		Builder initBuilder = ImmutableMap.builder()
				.put(MQ_URI, location.toString())
				.put(MQ_PUBSUB_URI, getLocalTransportURI(PROTOCOL_MQTT).toString())
				.put(MQ_PUBSUB_MQTT, Boolean.TRUE.toString());
		if(!Strings.isNullOrEmpty(getUsername()) && !Strings.isNullOrEmpty(getPassword())){
			initBuilder.put(MQ_USERNAME, getUsername())
							.put(MQ_PASSWORD, getPassword());
		}
		this.factory = MessageQueueFactorys.getFactory(MessageQueueType.ACTIVEMQ).init(initBuilder.build());
		return true;
	}

}
